package com.linkdood.app.exception;

import com.linkdood.app.constants.ErrorCode;
import com.linkdood.app.utils.ResourceUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.util.Arrays;
import java.util.Objects;

/**
 * 异常处理
 * @author YunJ
 */
@ControllerAdvice
public class ResponseExceptionHandler extends ResponseEntityExceptionHandler {

    /**
     * 处理参数异常的返回
     */
    @ExceptionHandler(value = InvalidParamException.class)
    protected ResponseEntity<Object> handleInvalidParamException(RuntimeException e, WebRequest webRequest) {
        String msg = ResourceUtil.getErrorMessage(ErrorCode.ERROR_INVALID_PARAM, e.getMessage());
        return handleExceptionInternal(e, msg,
            new HttpHeaders(),
            HttpStatus.BAD_REQUEST,
            webRequest);
    }

    /**
     * 一般性错误
     */
    @ExceptionHandler(value = GeneralException.class)
    protected ResponseEntity<Object> handleGeneralException(RuntimeException e, WebRequest webRequest) {
        String msg = ResourceUtil.getErrorMessage(e.getMessage());
        return handleExceptionInternal(e, msg,
            new HttpHeaders(),
            HttpStatus.BAD_REQUEST,
            webRequest);
    }

    /**
     * 用户不存在
     */
    @ExceptionHandler(value = UserNotFoundException.class)
    protected ResponseEntity<Object> handleUserNotFoundException(RuntimeException e, WebRequest webRequest) {
        String msg = ResourceUtil.getErrorMessage(ErrorCode.ERROR_USER_NOT_FOUND);
        return handleExceptionInternal(e, msg,
            new HttpHeaders(),
            HttpStatus.BAD_REQUEST,
            webRequest);
    }

    /**
     * 用户已经存在
     */
    @ExceptionHandler(value = UserExistException.class)
    protected ResponseEntity<Object> handleUserExistException(RuntimeException e, WebRequest webRequest) {
        String msg = ResourceUtil.getErrorMessage(ErrorCode.ERROR_USER_EXIST);
        return handleExceptionInternal(e, msg,
            new HttpHeaders(),
            HttpStatus.BAD_REQUEST,
            webRequest);
    }

    /**
     * 参数校验异常
     */
    @Override
    @NonNull
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, @NonNull HttpHeaders headers, @NonNull HttpStatus status, @NonNull WebRequest request) {
        String msg = "参数校验错误，请检查入参";
        if (ex.getBindingResult().hasFieldErrors()) {
            FieldError fieldError = ex.getBindingResult().getFieldError();
            assert fieldError != null;
            msg = fieldError.getField() + ": " + fieldError.getDefaultMessage();
        }
        msg = ResourceUtil.getErrorMessage(ErrorCode.ERROR_INVALID_PARAM, msg);
        return super.handleExceptionInternal(ex, msg, headers, status, request);
    }

    /**
     * 参数绑定异常
     */
    @Override
    @NonNull
    protected ResponseEntity<Object> handleBindException(BindException ex,
                                                         @NonNull HttpHeaders headers,
                                                         @NonNull HttpStatus status,
                                                         @NonNull WebRequest request) {
        String msg = ResourceUtil.getErrorMessage(ErrorCode.ERROR_INVALID_PARAM,
                Objects.requireNonNull(ex.getBindingResult().getFieldError()).getDefaultMessage());
        return super.handleExceptionInternal(ex, msg, headers, status, request);
    }

    /**
     * 请求类型不支持异常
     */
    @Override
    @NonNull
    protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
                                                                         @NonNull HttpHeaders headers,
                                                                         @NonNull HttpStatus status,
                                                                         @NonNull WebRequest request) {
        String method = ex.getMethod();
        String[] supportedMethods = ex.getSupportedMethods();
        String msg = "不支持的请求类型：" + method + "，支持的请求类型：" + Arrays.toString(supportedMethods);
        msg = ResourceUtil.getErrorMessage(ErrorCode.ERROR_INVALID_PARAM, msg);
        return super.handleExceptionInternal(ex, msg, headers, status, request);
    }

    /**
     * 缺少参数异常提示
     */
    @Override
    @NonNull
    protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
                                                                          @NonNull HttpHeaders headers,
                                                                          @NonNull HttpStatus status,
                                                                          @NonNull WebRequest request) {
        String msg = "缺少请求参数：" + ex.getParameterName() + ", 类型为：" + ex.getParameterType();
        msg = ResourceUtil.getErrorMessage(ErrorCode.ERROR_INVALID_PARAM, msg);
        return super.handleExceptionInternal(ex, msg, headers, status, request);
    }
}
